
#include "Flows.c"
#include "LongestMatch.c"

#include <assert.h>
#include <stdio.h>

void simpleTest();
void arpConstruct();
void ipConstruct();
void ethernetConstruct();
void matchTest();


int main() {
  
  matchTest();

  //simpleTest();
  //arpConstruct();
  //ipConstruct();
  //ethernetConstruct();

  //handlePacket( NULL, 0 );

}

void matchTest() {

  assert( bitsInCommon( 1, 2 ) == 30 );
  assert( bitsInCommon( 1, 1 ) == 32 );
  assert( bitsInCommon( -1, 1 ) == 0 );
  assert( bitsInCommon( 0x70ffffff, 0x7fffffff ) == 4 );
  assert( bitsInCommon( 0x7f0fffff, 0x7fffffff ) == 8 );
  assert( bitsInCommon( 0x7ff0ffff, 0x7fffffff ) == 12 );
  assert( bitsInCommon( 0x7fff0fff, 0x7fffffff ) == 16 );
  assert( bitsInCommon( 0x7ffff0ff, 0x7fffffff ) == 20 );
  assert( bitsInCommon( 0x7fffff0f, 0x7fffffff ) == 24 );
  assert( bitsInCommon( 0x7ffffff0, 0x7fffffff ) == 28 );
  

  


}


void ethernetConstruct() {

  uint8_t src[6] = {0x7e, 0x7b, 0xc6, 0x7b, 0xd6, 0xe9};
  uint8_t dest[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  
  ethernetHeader arp;
  ethernetHeader ip;

  printf("\nEthernet Arp: \n");
  constructEthernetArp( &arp, src, dest );
  int i;
  for (i = 0; i < 14; i ++ ) {
    if ( ! (i % 8) ) {
      printf( "\n" );
    }
    printf(" %2x ", arp.data[i] );
  }

  printf("\n\n");

  printf("\nEthernet IP: \n");
  constructEthernetIP( &ip, src, dest );
  
  for (i = 0; i < 14; i ++ ) {
    if ( ! (i % 8) ) {
      printf( "\n" );
    }
    printf(" %2x ", ip.data[i] );
  }

  ethernetHeader p1;
  memcpy( p1.data, ip.data, 14 );
  parseEthernet( &p1 );
  assert (p1.ip_flag);
  assert (!p1.arp_flag);
  

  memcpy( p1.data, arp.data, 14 );
  parseEthernet( &p1 );
  assert (!p1.ip_flag);
  assert (p1.arp_flag);
  

  printf("\n\n");

}

void ipConstruct() {
  
  uint8_t src[4] = {10, 0, 1, 1};
  uint8_t dest[4] = {10, 0, 1, 100};
  
  ipHeader h;
  constructIP( &h, src, dest, 56, 100, 1 );

  int i;
  for (i = 0; i < 20; i++) {
    if ( ! (i % 8) ) {
      printf( "\n" );
    }
    printf(" %2x ", h.header[i] );
    
  }
  printf("\n\n");

  ipHeader rev;
  memcpy (rev.header, h.header, 20);
  parseIP( &rev );
  assert ( rev.version == 4 );
  assert (rev.headerLen == 5);
  assert (rev.totalLength == 56 );
  assert (rev.ttl == 100);
  assert (rev.protocol == 1 );
  assert (rev.srcIP[0] == 10);
  assert (rev.srcIP[1] == 0);
  assert (rev.srcIP[2] == 1);
  assert (rev.srcIP[3] == 1);
  assert (rev.destIP[0] == 10);
  assert (rev.destIP[1] == 0);
  assert (rev.destIP[2] == 1);
  assert (rev.destIP[3] == 100);

  printf("\nReverse Interpretation passed\n\n");


}

void arpConstruct() {
  
  uint8_t dest[6] = {0x42, 0x07, 0xe8, 0x35, 0x11, 0xe0 };
  uint8_t src[6] = {0x36, 0xec, 0xca, 0xd4, 0x53, 0xa8};
  uint8_t srcIP[4] = {10, 0, 1, 100};
  uint8_t destIP[4] = {10, 0, 1, 1};

  arpHeader request;

  arpResponse( &request, src, dest, srcIP, destIP );

  int i;
  for (i = 0; i < 28; i++) {
    if ( ! (i % 8) ) {
      printf( "\n" );
    }
    printf(" %2x ", request.data[i] );
    
  }

  arpHeader req;
  memcpy( req.data, request.data, 28 );
  parseArp( &req );
  assert( req.operation == 2 );
  for (i = 0; i < 6; i++) {
    assert( src[i] == req.senderAddr[i] );
    assert( dest[i] == req.receiverAddr[i] );
  }
  for (i = 0; i < 4; i++) {
    assert( srcIP[i] == req.senderIP[i] );
    assert( destIP[i] == req.receiverIP[i] );
  }

  
  arpRequest( &req, dest, destIP, srcIP );
  printf("\n\n");

  for (i = 0; i < 28; i++) {
    if ( ! (i % 8) ) {
      printf( "\n" );
    }
    printf(" %2x ", req.data[i] );
    
  }
  
  memcpy( request.data, req.data, 28 );
  parseArp( &request );
  assert( req.operation == 1 );
  for (i = 0; i < 6; i++) {
    assert( dest[i] == req.senderAddr[i] );
    //assert( dest[i] == req.receiverAddr[i] );
  }
  for (i = 0; i < 4; i++) {
    assert( destIP[i] == req.senderIP[i] );
    assert( srcIP[i] == req.receiverIP[i] );
  }


  printf("\n\n");
  

}


void simpleTest() {
  int i;
  /*
  printf("\n\nTesting Arp Parsing: ");
  for (i = 0; i < 10; i ++ ) {
  
    arpHeader arp;
    arp.senderIP = (10 * i + 2);
    arp.receiverIP = (12*i + 4);
    arp.operation = i;
    arpRequest( &arp );
    
    arpHeader toParse;
    memcpy( toParse.data, arp.data, 28 );
    parseArp( &toParse );

    assert (toParse.senderIP == (10*i + 2));
    assert (toParse.receiverIP == (12*i + 4));
    assert (toParse.operation == i);
    printf(" . ");
  }
  printf("  PASS");
  

  printf("\n Testing IP Parsing: ");
  for (i = 0; i < 10; i ++ ) {
    ipHeader ip;
    ip.totalLength = 30 * i;
    ip.ttl = i;

    ip.protocol = i;
    ip.checksum = 31 * i;
    ip.srcIP = 5000 * i;
    ip.destIP = 6000 * i;
    
    
    constructIP ( &ip );

    ipHeader toParse;
    memcpy( toParse.header, ip.header, 28 );
    parseIP( &toParse );
    assert ( toParse.totalLength == (30 * i ) );
    assert ( toParse.ttl == i );
    assert ( toParse.protocol == i );
    assert ( toParse.checksum == (31 * i ) );
    assert ( toParse.srcIP == (5000 * i ) );
    assert ( toParse.destIP == (6000 * i ) );
    
    printf(" . ");
  }
  printf("  PASS\n\n\n");
  */
}
